package br.ufrn.cerescaico.sepe.bo;

import br.ufrn.cerescaico.sepe.Sepe;
import br.ufrn.cerescaico.sepe.actions.SepeAction;
import br.ufrn.cerescaico.sepe.beans.Email;
import br.ufrn.cerescaico.sepe.beans.Participante;
import br.ufrn.cerescaico.sepe.dao.Dao;
import br.ufrn.cerescaico.sepe.dao.ParticipanteDao;
import br.ufrn.cerescaico.sepe.dao.util.DataAccessLayerException;
import br.ufrn.cerescaico.sepe.email.MailManager;
import br.ufrn.cerescaico.sepe.email.MailMessage;
import br.ufrn.cerescaico.sepe.util.Constantes;
import br.ufrn.cerescaico.sepe.util.RandomAlphaNumeric;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import org.apache.log4j.Logger;

/**
 * Classe de negócio do bean participante do sistema Sepe.
 * @author Taciano Morais Silva
 * @version 16/08/2010, 18h30m
 * @since 16/08/2010, 18h30m
 */
public class ParticipanteBO extends AbstractBO {

    /**
     * Logger.
     */
    private Logger logger = Logger.getLogger(ParticipanteBO.class);

    /**
     * 
     * @param Sepe
     */
    public ParticipanteBO(Sepe Sepe) {
        super(Sepe);
    }

    /**
     * Autentica o participante. Se não for possível autenticar o participante será
     * retornado <code>null</code>.
     * @param username Login do participante, neste caso o e-mail.
     * @param password Senha do participante.
     * @return O participante autenticado, ou <code>null</code> caso contrário.
     * @throws SepeException Casp ocorra algum erro de acesso ao banco.
     */
    public Participante autenticar(String username, String password) throws SepeException {
        try {
            ParticipanteDao dao = new ParticipanteDao();
            return dao.autenticar(username, password);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.autenticar", ex);
        }
    }

    /**
     * Lista todos os participantes cadastrados no sistema.
     * @return A lista de participantes.
     */
    public List<Participante> listar() throws SepeException {
        try {
            Dao<Participante> dao = new ParticipanteDao();
            return dao.findAll();
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.listar", ex);
        }
    }

        /**
     * Lista todos os participantes cadastrados no sistema.
     * @return A lista de participantes.
     */
    public List<Participante> listarOrdenadoPorEmail() throws SepeException {
        try {
            ParticipanteDao dao = new ParticipanteDao();
            return dao.findAllOrderByEmail();
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.listar", ex);
        }
    }

    /**
     * Busca o participante a partir do seu identificador.
     * @param id O identificador do participante.
     * @return O participante localizado.
     */
    public Participante buscar(Integer id) throws SepeException {
        try {
            Dao<Participante> dao = new ParticipanteDao(getSepe());
            return dao.find(id);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.buscar", ex);
        }
    }

    /**
     * Busca o participante a partir do seu identificador.
     * @param id O identificador do participante.
     * @return O participante localizado.
     */
    public Participante buscar(String email) throws SepeException {
        try {
            ParticipanteDao dao = new ParticipanteDao(getSepe());
            return dao.find(email);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.buscar.email", ex);
        }
    }

    /**
     * Incluir um participante do evento no sistema.
     * @param participante O participante a ser incluído.
     */
    public void incluir(Participante participante) throws SepeException {
        verificarNull(participante);
        verificarEmailExistente(participante);

        participante.setSenha(RandomAlphaNumeric.randomString(6, 10));
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(new Date());
        Date data = calendar.getTime();
        participante.setDataCadastro(data);
        try {
            Dao<Participante> dao = new ParticipanteDao();
            enviarEmail(participante);
            dao.create(participante);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.incluir", ex);
        }
    }

        /**
     * Incluir um participante do evento no sistema.
     * @param participante O participante a ser incluído.
     */
    public void reenviarSenha(Participante participante) throws SepeException {
        verificarNull(participante);

        try {
            ParticipanteDao dao = new ParticipanteDao();
            Participante participanteBD = dao.verificarEmailExistente(participante);
            if (participanteBD == null) {
                logger.error("erro.participante.bo.reenviarSenha.naocadastrado");
                throw new SepeException("erro.participante.bo.reenviarSenha.naocadastrado");
            }
            enviarEmail(participanteBD);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.reenviarSenha", ex);
        }
    }

    private void verificarNull(Object obj) throws SepeException {
        if (obj == null) {
            throw new SepeException("erro.participante.bo.null");
        }
    }

    private void verificarEmailExistente(Participante participante) throws SepeException {
        try {
            if (participante == null) {
                throw new DataAccessLayerException("erro.participante.bo.participante.null");
            }
            ParticipanteDao dao;
            dao = new ParticipanteDao();
            Participante participanteBD = dao.verificarEmailExistente(participante);

            if (participanteBD != null && !participanteBD.getId().equals(participante.getId())) {
                throw new DataAccessLayerException("erro.participante.dao.participante.duplicado");
            }
        } catch (DataAccessLayerException e) {
            throw new SepeException("erro.participante.email.existente", e);
        }

    }

    /**
     * Alterar os dados do participante.
     * @param participante O participante a ser alterado.
     */
    public void alterar(Participante participante) throws SepeException {
        verificarNull(participante);
        recuperarSenha(participante);
        getSepe().closeSessaoHibernate();
        try {
            Dao<Participante> dao = new ParticipanteDao();
            dao.update(participante);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.alterar", ex);
        }
    }

    private void recuperarSenha(Participante participante) throws SepeException {
        Participante bd = buscar(participante.getId());
        if (bd == null) {
            throw new SepeException("erro.bo.participante.alterar.nao.cadastrado");
        }
        participante.setSenha(bd.getSenha());
    }

    /**
     * Exclui o participante do sistema.
     * @param participante O participante a ser excluído.
     */
    public void excluir(Participante participante) throws SepeException {
        try {
            Dao<Participante> dao = new ParticipanteDao();
            dao.delete(participante);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.excluir", ex);
        }
    }

    /**
     * Exclui o participante do sistema.
     * @param id O identificador do participante a ser excluído.
     */
    public void excluir(Integer id) throws SepeException {
        try {
            Dao<Participante> dao = new ParticipanteDao();
            dao.delete(id);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.excluir.id", ex);
        }
    }

    /**
     * Pesquisar participante filtrando por email e nome.
     * @param email O email do participante.
     * @param nome O nome do participante.
     */
    public List<Participante> pesquisar(String email, String nome) throws SepeException {
        try {
            ParticipanteDao dao = new ParticipanteDao();
            return dao.pesquisar(email, nome);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.participante.bo.pesquisar", ex);
        }
    }

    /**
     *
     * @param texto
     * @throws br.cesed.lti.Sepe.bo.SepeException
     */
    private void verificarTamMin(String att, String texto) throws SepeException {
        if (texto == null || texto.equals(STRING_VAZIO)
                || texto.length() < TAMANHO_MINIMO) {
            String[] parametros = {att, TAMANHO_MINIMO + ""};
            throw new SepeException("erro.participante.bo.pesquisar.tam.min", parametros);
        }
    }

    private void enviarEmail(Participante participante) throws SepeException {
        Email mail = new Email();
        mail.setDestino(participante.getEmail());
        mail.setAssunto("[II Semana de Ensino, Pesquisa e Extensão do CERES/UFRN] Confirmação de Cadastro");
        mail.setConteudo(msg(participante));

        MailMessage mailMessage = getMailMessage(mail);
        MailManager m = new MailManager();
        
        try {
            m.send(mailMessage);
            EmailBO emailBO = new EmailBO(getSepe());
            emailBO.incluir(mail);
        } catch (Exception ex) {
            logger.error("erro.participante.bo.incluir.email.naoenviado", ex);
            throw new SepeException("erro.participante.bo.incluir.email.naoenviado");
        }
    }



    private String msg(Participante p) {
        String msg = "Prezado(a) " + p.getNome() + ",\n\n";
        msg += "Os dados de inscri\u00e7\u00e3o cadastrados em nossa base de dados s\u00e3o os seguinte: \n";
        msg += "      - E-mail: " + p.getEmail() + "\n";
        msg += "      - Senha: " + p.getSenha() + "\n\n";
        msg += "Para mais informa\u00e7\u00f5es sobre a II Semana de Ensino, Pesquisa e Extensão do CERES/UFRN, por favor, \n"
                + "reporte-se ao portal web do evento (" + Constantes.SITE + ").\n\n";
        msg += "Atenciosamente,\n";
        msg += "Comiss\u00e3o Organizadora II SEPE.";
        return msg;
    }
}
